﻿using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using xycn.common;
using xycn.IAuthorize;

namespace xycn.JwtAuthorize
{

    /// <summary>
    /// 类工厂，数据库接口库，需要同时实现该接口
    /// </summary>
    public class AuthorizeFactory : IPluginFactory.IPluginFactory
    {
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public override IAuthorize.IAuthorize CreatePlugin()
        {
            return new JwtAuthorizeHelper();
        }
    }

    /// <summary>
    /// Jwt实现认证签名
    /// </summary>
    public class JwtAuthorizeHelper : IAuthorize.IAuthorize
    {
        /// <summary>
        /// 获取签名信息 Authorization 授权后访问需带上 Authorization：Bearer {Token}
        /// </summary>
        /// <param name="authInfo"></param>
        /// <returns></returns>
        public string CreateSign(SignInfo authInfo)
        {
            // 定义用户信息
            var claims = new Claim[]
            {
                new Claim("id", authInfo.id??""),
                new Claim("name", authInfo.name??""),
                new Claim("groupid", authInfo.groupid??""),
                new Claim("extend1", authInfo.extend1??""),
                new Claim("extend2", authInfo.extend2??""),
                new Claim("extend3", authInfo.extend3??""),
                new Claim("extend4", authInfo.extend4??""),
            };

            SymmetricSecurityKey key = new SymmetricSecurityKey(
                Encoding.UTF8.GetBytes(XmlConfigHelper.GetConfigToString("/Config/JwtSignInfo/UserKey")));

            var expiresAt = DateTime.Now.AddDays(XmlConfigHelper.GetConfigToInt("/Config/JwtSignInfo/ExpiresDays"));

            //var tokenDescriptor = new SecurityTokenDescriptor
            //{
            //    Subject = new ClaimsIdentity(claims),//创建声明信息
            //    Issuer = XmlConfigHelper.GetConfigToString("/Config/AuthSignInfo/FromUser"),//Jwt token 的签发者
            //    Audience = XmlConfigHelper.GetConfigToString("/Config/AuthSignInfo/ToUser"),//Jwt token 的接收者
            //    NotBefore = DateTime.Now,
            //    Expires = expiresAt,//过期时间
            //    SigningCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256)//创建 token
            //};

            JwtSecurityToken token = new JwtSecurityToken(
                issuer: XmlConfigHelper.GetConfigToString("/Config/JwtSignInfo/FromUser"),//Jwt token 的签发者
                audience: XmlConfigHelper.GetConfigToString("/Config/JwtSignInfo/ToUser"),//Jwt token 的接收者
                claims: claims,
                notBefore: DateTime.Now,
                expires: expiresAt,
                signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256)
            );

            return new JwtSecurityTokenHandler().WriteToken(token);
        }

        /// <summary>
        /// 获取认证信息
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public SignInfo GetSignInfo(string token)
        {
            IJsonSerializer serializer = new JsonNetSerializer();
            IDateTimeProvider provider = new UtcDateTimeProvider();
            IJwtValidator validator = new JwtValidator(serializer, provider);
            IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
            IJwtAlgorithm alg = new HMACSHA256Algorithm();
            IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, alg);

            var json = decoder.Decode(token?.Replace("Bearer ", ""), XmlConfigHelper.GetConfigToString("/Config/JwtSignInfo/UserKey"), true);
            //校验通过，返回解密后的字符串
            return json.GetModelByJson<SignInfo>();
        }

        /// <summary>
        /// 从Token解密出JwtSecurityToken,JwtSecurityToken : SecurityToken
        /// </summary>
        /// <param name="tokenStr"></param>
        /// <returns></returns>
        private JwtSecurityToken GetJwtSecurityToken(string tokenStr)
        {
            var jwt = new JwtSecurityTokenHandler().ReadJwtToken(tokenStr);
            return jwt;
        }

        /// <summary>
        /// 验证签名是否正确
        /// 1.验证Token是否是符合要求的标准 Json Web 令牌
        /// 2.
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public bool IsSuccess(string token)
        {
            if (string.IsNullOrWhiteSpace(token) || token.Length < 7)
                return false;

            if (!token.Substring(0, 6).Equals(Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme))
                return false;
            token = token.Substring(7);

            bool isCan = new JwtSecurityTokenHandler().CanReadToken(token);

            if (isCan)
            {
                IJsonSerializer serializer = new JsonNetSerializer();
                IDateTimeProvider provider = new UtcDateTimeProvider();
                IJwtValidator validator = new JwtValidator(serializer, provider);
                IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
                IJwtAlgorithm alg = new HMACSHA256Algorithm();
                IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, alg);

                try
                {
                    var json = decoder.Decode(token, XmlConfigHelper.GetConfigToString("/Config/JwtSignInfo/UserKey"), true);
                    //校验通过，返回解密后的字符串
                    return !string.IsNullOrWhiteSpace(json);
                }
                catch (Exception ex)
                {
                    return false;
                }
            }
            return isCan;
        }


    }
}
